'''
Created on 27/03/2010

@author: kivson
'''
import Base.TSR
import string

class AnaLex(object):
    '''
    Analisador Lexico LALG
    '''
    l = string.letters
    b = string.whitespace
    d = string.digits
    c = string.printable

    def __init__(self, tabelaSimbolos, entrada, formatoToken = '<{nome}, {classe}>'):
        '''
        Constructor
        '''
        self.__linhaAtual = 1
        self.__tabelaSimbolos = tabelaSimbolos
        self.__formatoToken = formatoToken
        self.__entrada = entrada
        self.__saida = []
        self.__entradaLista = []
        self.__token = ''
        self.__erro = False


    def getListTokens(self):
        return self.__saida

    def get_entrada(self):
        return self.__entrada


    def set_entrada(self, value):
        self.__entrada = value


    def get_tabela_simbolos(self):
        return self.__tabelaSimbolos


    def get_formato_token(self):
        return self.__formatoToken


    def get_saida(self):
        for token in self.__saida:
            print "<%s, %s, %d>" % token


    def set_tabela_simbolos(self, value):
        self.__tabelaSimbolos = value


    def set_formato_token(self, value):
        self.__formatoToken = value
        
     
    def analisa(self):
        self.__erro = False
        self.__entradaLista = list(self.entrada)
        while self.__entradaLista and not self.__erro:
            self.__s0()
        
        #print self.__saida
            
    def __s0(self):
        c = self.pop()
        if c == '{':
            self.__s8()
        elif c in self.b:
            return
        elif c in self.l:
            self.__token = ''
            self.__token += c
            self.__s1()
            return
        elif c == '/':
            self.__token = ''
            self.__token += c
            self.__s4()
            return
        elif c in self.d:
            self.__token = ''
            self.__token += c
            self.__s2()
            return
        else:
            self.__token = ''
            self.__token += c
            self.__s3()
        
        
    def __s3(self):
        c = self.pop()
        if c in self.l + self.d + self.b:
            self.push(c)
            if not self.tabelaSimbolos.getToken((self.__token, None)):
                self.__fail()
                return
            self.__saida.append((self.__token,"<operador>" ,self.__linhaAtual))
            
            return 
        else:
            if self.tabelaSimbolos.getToken((self.__token + c, None)):
                self.__token += c
                self.__saida.append((self.__token,"<operadorDuplo>" ,self.__linhaAtual))
            else:
                self.push(c)
                if not self.tabelaSimbolos.getToken((self.__token, None)):
                    self.__fail()
                    return
                self.__saida.append((self.__token,"<operador>" ,self.__linhaAtual))
            return 
            
    def __s8(self):
        while self.pop() != '}':
            pass
        return
    
    def __s4(self):
        c =self.pop()
        if c == '*':
            self.__s5()
        else:
            self.push(c)
            self.__saida.append((self.__token,"<operador>" ,self.__linhaAtual))
            
            #o simbolo pode jah esta na tabela pre carregada.
            return      
    def __s5(self):
        c =self.pop()
        while c != '*':
            c =self.pop()
        self.__s6()
    
    def __s6(self):
        c =self.pop()
        while c == '*':
            c =self.pop()
        if c == '/':
            return
        else:
            self.__s5()
        
    def __s1(self):
        c =self.pop()
        while c in self.l + self.d:
            self.__token += c
            c =self.pop()
        self.push(c)
        if self.tabelaSimbolos.getToken((self.__token,None)):
            self.__saida.append((self.__token,"<palavraReservada>" ,self.__linhaAtual))
            return
        self.__saida.append((self.__token,"<identificador>" ,self.__linhaAtual))
        return      
    
    def __s2(self):
        c =self.pop()
        while c in self.d:
            self.__token += c
            c =self.pop()
        if c == '.':
            self.__token += c
            self.__s9()
            return
        self.push(c)
        self.__saida.append((self.__token,"<inteiro>" ,self.__linhaAtual))
        return
     
    def __s9(self):
        c =self.pop()
        while c in self.d:
            self.__token += c
            c =self.pop()
        self.push(c)
        self.__saida.append((self.__token,"<real>" ,self.__linhaAtual))
        return
    
    
    def __fail(self):
        self.__erro = True
        raise SystemExit, 'Erro Lexico na linha %d' % self.__linhaAtual
    def pop(self):
        c = self.__entradaLista.pop(0)
        if c == '\n':
            self.__linhaAtual +=1
        return c
    def push(self,charIN):
        if charIN == '\n':
            self.__linhaAtual -=1
        self.__entradaLista.insert(0, charIN)
        
        
    tabelaSimbolos = property(get_tabela_simbolos, set_tabela_simbolos, None, None)
    formatoToken = property(get_formato_token, set_formato_token, None, None)
    saida = property(get_saida, None, None, None)
    entrada = property(get_entrada, set_entrada, None, None)






if __name__=='__main__':
    tabelaF = file ('../Tabela.txt')
    tabelaStr = tabelaF.read()
    tabela = Base.TSR.TabelaRS();
    tabela.carregaTabelaString(tabelaStr)
    f = file('../lalg')
    s = f.read()
    a = AnaLex(tabela, s )
    print 'tabela =>', a.tabelaSimbolos.tokens
    a.analisa()
    print 'tabela =>', a.tabelaSimbolos.tokens, '\n\n\n'
    
    print a.saida
